Skip to content

Structural history schema authority#57

Merged
flyingrobots merged 15 commits into
mainfrom
cycle/CORE_structural-history-schema-authority
May 27, 2026
Merged

Structural history schema authority#57
flyingrobots merged 15 commits into
mainfrom
cycle/CORE_structural-history-schema-authority

Conversation

@flyingrobots
Copy link
Copy Markdown
Owner

@flyingrobots flyingrobots commented May 16, 2026

Summary

  • add Graft's canonical structural history GraphQL schema
  • commit Wesley-generated TypeScript contracts plus a manifest recording schema, generated artifact, and Wesley L1 hashes
  • add deterministic schema/generated artifact drift checks and focused contract tests
  • document the first implementation status and file bad-code for making Wesley CLI regeneration hermetic in Graft CI

Verification

  • pnpm schema:structural-history:check
  • pnpm exec vitest run test/unit/contracts/graft-structural-history-schema.test.ts
  • pnpm typecheck
  • pnpm lint
  • NODE_OPTIONS=--no-deprecation pnpm test:local (one unrelated playback timed out in full host run; direct rerun passed)
  • NODE_OPTIONS=--no-deprecation pnpm exec vitest run tests/playback/WARP_dead-symbol-detection.test.ts
  • pnpm test (Docker isolated): 221 files / 1608 tests passed

Summary by CodeRabbit

  • New Features

    • Workspace management: open workspaces and list opened workspaces with activation status, source, timestamps, and session metadata; new workspace tool endpoints and capability entries.
  • Chores

    • Added a Graft structural-history GraphQL schema and manifest, plus a validation script and npm script; ESLint now ignores generated sources; capability baseline updated to include two workspace tools.
  • Tests

    • New unit and playback tests covering workspace open/list behaviors and schema/artifact validations.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 16, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a GraphQL structural-history schema with manifest, a checker script, and tests; and implements MCP workspace open/list-opened end-to-end (contracts, Zod output schemas, ToolContext wiring, tool definitions, workspace-router tracking/activation, and unit/playback tests).

Changes

Structural History Schema and Validation

Layer / File(s) Summary
GraphQL Schema: Types, Enums, and Query API
schemas/graft-structural-history.graphql
Defines the structural history data model with custom scalars (Hash, Json), enums for basis/reading/evidence/substrate kinds and symbol taxonomy, codec-annotated object types for repositories, bases, file versions, symbols, relations, readings, evidence, and git-warp batches, Query entry points with @wes_op/@wes_footprint, and an invariant constraining fallback-translated evidence.
Schema Manifest and Artifact Verification Script
schemas/graft-structural-history.manifest.json, scripts/check-structural-history-schema-artifacts.ts
Adds a manifest JSON declaring source/generated file paths, SHA-256 content hashes, Wesley metadata, and required type/query/evidence names. Implements a checker that computes and verifies hashes, enforces the generated header prefix and Wesley CLI version, confirms required exported types/constants, and ensures evidence labels exist in both schema and generated outputs; reports violations or success.
Schema Contract Tests
test/unit/contracts/graft-structural-history-schema.test.ts
Vitest suite asserting artifact checks report zero violations, validating manifest evidence labels and Wesley version, verifying generated operations’ wes_footprint.reads labels, and testing generated types’ literal-kind shapes and fields.
Build and Linting Configuration
eslint.config.js, package.json
Updates ESLint to ignore src/generated/ and adds schema:structural-history:check npm script to run the artifact validation and updates pnpm overrides.

MCP Workspace Open / List-Opened

Layer / File(s) Summary
Contracts: capabilities & output schemas
src/contracts/capabilities.ts, src/contracts/output-schema-fragments.ts, src/contracts/output-schema-mcp.ts, src/contracts/output-schemas.ts
Adds MCP tool names workspace_open and workspace_list_opened to capability registry and fragment maps; introduces Zod schemas/fragments for opened-workspace views and registers workspace_open/workspace_list_opened under MCP output body schemas and exported MCP_OUTPUT_SCHEMAS.
Burden, ToolContext & Server Access
src/mcp/burden.ts, src/mcp/context.ts, src/mcp/repo-tool-worker-context.ts, src/mcp/server-context.ts, src/mcp/server-tool-access.ts
Marks new tools as "diagnostic", extends ToolContext with open/list signatures, provides unsupported stubs for repo-tool-worker, delegates real methods in server ToolContext to workspaceRouter, and adds tools to daemon/repo allowlists.
Tool Registry and Tool Definitions
src/mcp/tool-registry.ts, src/mcp/tools/workspace-open.ts, src/mcp/tools/workspace-list-opened.ts
Registers workspaceOpenTool and workspaceListOpenedTool in TOOL_REGISTRY (adjusts DAEMON_TOOL_REGISTRY), and adds both tool definitions with Zod input validation and handlers that call ToolContext methods and respond with the resulting payloads.
Workspace Router Model Types
src/mcp/workspace-router-model.ts
Adds OpenedWorkspaceSource, OpenedWorkspaceView, WorkspaceOpenRequest, WorkspaceOpenResult, and WorkspaceListOpenedResult model types used by router and ToolContext.
WorkspaceRouter implementation
src/mcp/workspace-router.ts
Introduces openedWorkspaces tracking and OpenedWorkspaceRecord, records startup-opened workspace, implements listOpenedWorkspaces(), implements openWorkspace() with resolution/authorization, capability selection, activation semantics, and rebinding, extends bindInternal to accept openedSource, and adds helpers to note/convert opened-workspace records.
Unit & Playback Tests
test/unit/mcp/opened-workspaces.test.ts, test/unit/contracts/output-schemas.test.ts, test/unit/contracts/capabilities.test.ts, tests/playback/*
Adds unit tests for opened-workspace behaviors and output-schema validation, updates capability baseline counts (api+mcp increased from 22→24), and adds playback tests covering opened-workspace paths, activation, persistence, daemon-mode behavior, and repo-relative responses.

Sequence diagram (MCP workspace open/list flow):

sequenceDiagram
  participant Client
  participant ToolRegistry
  participant WorkspaceOpenTool
  participant WorkspaceRouter
  participant Storage
  Client->>ToolRegistry: invoke workspace_open(cwd, activate?)
  ToolRegistry->>WorkspaceOpenTool: dispatch to handler
  WorkspaceOpenTool->>WorkspaceRouter: ctx.openWorkspace(request)
  WorkspaceRouter->>Storage: resolve workspace & persist openedWorkspaces
  Storage-->>WorkspaceRouter: persistence result
  WorkspaceRouter-->>WorkspaceOpenTool: WorkspaceOpenResult
  WorkspaceOpenTool-->>Client: respond("workspace_open", payload)
Loading

🎯 4 (Complex) | ⏱️ ~45 minutes

"🐰 I hopped through types and lines of code,
Manifest clenched tight like a carrot bode,
Routers now track each opened den,
Tools respond and tests prove when."

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.69% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Structural history schema authority' directly and clearly summarizes the main change: adding Graft's canonical structural history GraphQL schema and related schema-validation infrastructure.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cycle/CORE_structural-history-schema-authority

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 89a7641b90

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/check-structural-history-schema-artifacts.ts Outdated
@flyingrobots
Copy link
Copy Markdown
Owner Author

@coderabbitai review please

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 24, 2026

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Get the PR details and files changed
gh pr view 57 --repo flyingrobots/graft

echo "---FILES CHANGED---"
gh pr diff 57 --repo flyingrobots/graft --name-only

echo "---PR DIFF---"
gh pr diff 57 --repo flyingrobots/graft

Length of output: 111667


@flyingrobots — clean, well-scoped slice. The schema-first approach before wiring Echo is the right sequencing, and the deterministic artifact drift check is a solid foundation. A few things worth looking at:


🔴 Hard-coded wesleyCliVersion check in check-structural-history-schema-artifacts.ts

// scripts/check-structural-history-schema-artifacts.ts  (~line 125)
if (manifest.wesleyCliVersion !== "0.0.4") {
  violations.push(`Unexpected Wesley CLI version ${manifest.wesleyCliVersion}; expected 0.0.4.`);
}

The manifest already carries wesleyCliVersion as the authoritative record. Hard-coding "0.0.4" directly in the script body means every Wesley CLI bump requires a two-file change (manifest + script) and risks the script silently drifting out of sync. The wesleyL1RegistryHash is already the stronger invariant here. Consider either removing this assertion entirely, or deriving the expected version from a constant at the top of the script so the intent is explicit:

const SUPPORTED_WESLEY_CLI_VERSION = "0.0.4";
// ...
if (manifest.wesleyCliVersion !== SUPPORTED_WESLEY_CLI_VERSION) { ... }

That at minimum surfaces the coupling at declaration time rather than buried in the check loop.


🟡 StructuralSourceSpan has no relational constraint on offsets/lines

# schemas/graft-structural-history.graphql
startOffset: Int! `@wes_stateField` `@wes_constraint`(min: 0)
endOffset: Int! `@wes_stateField` `@wes_constraint`(min: 0)
startLine: Int `@wes_stateField` `@wes_constraint`(min: 1)
endLine: Int `@wes_stateField` `@wes_constraint`(min: 1)

Both individual fields are constrained to be ≥ 0 (or ≥ 1), but nothing prevents endOffset < startOffset or endLine < startLine. If Wesley's invariant DSL supports cross-field expressions like the one already used on GraftStructuralHistoryInvariants, a companion invariant (e.g., endOffset >= startOffset) would close this gap before Echo import wires these spans for real.


🟡 StructuralSourceSpan is absent from requiredTypes in the manifest

StructuralSourceSpan is a full @wes_registry(id: 515) type in the schema and is referenced via spanId in both StructuralSymbol and StructuralSymbolRelation, but it does not appear in manifest.requiredTypes. If that's intentional (e.g., span storage is deferred to a later slice), it's worth a brief comment in the manifest to document why.


🟡 Regex built from unsanitized manifest input in typePattern

// scripts/check-structural-history-schema-artifacts.ts
function typePattern(typeName: string): RegExp {
  return new RegExp(`export (interface|type) ${typeName}\\b`, "u");
}

typeName comes from manifest.requiredTypes, which is read from a JSON file. TypeScript type names are alphanumeric so this is safe in practice, but if the manifest were ever tampered with or contained unexpected characters, this would silently break or throw an uncaught SyntaxError during new RegExp(...). A lightweight guard like typeName.replace(/[^A-Za-z0-9_]/g, "") before interpolation would make it resilient.


🟢 Minor nit — _placeholder in GraftStructuralHistoryInvariants

type GraftStructuralHistoryInvariants
  `@wes_invariant`(...) {
  _placeholder: Boolean
}

This is a known GraphQL limitation (a type must have at least one field). A short inline comment explaining the placeholder's purpose would help future readers understand this isn't accidental:

  _placeholder: Boolean  # Required: GraphQL types must declare at least one field.

✅ What's solid

  • The manifest + SHA-256 drift check approach is clean and deterministic.
  • Excluding src/generated/ from ESLint is the right call.
  • The bad-code backlog item (CLEAN_wesley-cli-not-hermetic-in-graft-ci.md) accurately captures the remaining risk and its acceptance criteria are precise.
  • Contract tests exercise real behavioral invariants (the FALLBACK_TRANSLATED → nativeContinuumWitness == false rule is encoded both in the schema and in test fixtures), not just structural presence.
  • isMainModule() guard using import.meta.url === pathToFileURL(process.argv[1]).href is the correct ESM idiom.
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@schemas/graft-structural-history.manifest.json`:
- Around line 8-18: The manifest's requiredTypes array is missing
StructuralSourceSpan, so add "StructuralSourceSpan" to the requiredTypes list in
the manifest (the requiredTypes JSON array) to ensure artifact verification
enforces that canonical type; update the array alongside existing entries like
"StructuralRepository", "StructuralBasis", "StructuralFileVersion", etc.,
preserving JSON formatting and commas.

In `@scripts/check-structural-history-schema-artifacts.ts`:
- Around line 112-114: Replace the hard-coded expected version string with a
single exported constant and use that constant everywhere; create and export
(e.g. EXPECTED_WESLEY_CLI_VERSION or WESLEY_CLI_VERSION) from a shared module
(or from scripts/check-structural-history-schema-artifacts.ts if you prefer a
central export) and then update the check that compares
manifest.wesleyCliVersion (the if block that pushes to violations) to use that
exported constant, and update the contract test to import and assert against the
same constant so there is a single source of truth.
- Around line 82-84: The code builds a RegExp from manifest.requiredTypes
without escaping, which allows malformed manifest strings to produce invalid
regexes; update the typePattern function (and any call sites that interpolate
requiredTypes) to escape regex metacharacters in typeName before constructing
new RegExp (e.g. replace characters like . * + ? ^ $ { } ( ) | [ ] \ / with
escaped versions) so the literal type names are matched safely and do not throw;
keep the existing pattern structure (matching "export (interface|type)
<typeName>\\b" with the "u" flag) after escaping.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d9958cab-bc97-4030-a8e5-7c1a64bfd289

📥 Commits

Reviewing files that changed from the base of the PR and between 9f83c4f and 89a7641.

⛔ Files ignored due to path filters (6)
  • CHANGELOG.md is excluded by !**/*.md
  • docs/design/CORE_structural-history-schema-and-echo-migration.md is excluded by !**/*.md
  • docs/method/backlog/bad-code/CLEAN_wesley-cli-not-hermetic-in-graft-ci.md is excluded by !**/*.md
  • docs/method/backlog/dependency-dag.dot is excluded by !**/*.dot
  • docs/method/backlog/dependency-dag.svg is excluded by !**/*.svg
  • src/generated/graft-structural-history.ts is excluded by !**/generated/**
📒 Files selected for processing (6)
  • eslint.config.js
  • package.json
  • schemas/graft-structural-history.graphql
  • schemas/graft-structural-history.manifest.json
  • scripts/check-structural-history-schema-artifacts.ts
  • test/unit/contracts/graft-structural-history-schema.test.ts

Comment thread schemas/graft-structural-history.manifest.json
Comment thread scripts/check-structural-history-schema-artifacts.ts
Comment thread scripts/check-structural-history-schema-artifacts.ts Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/mcp/context.ts`:
- Around line 97-98: The type guard assertToolContext was not updated to check
the new required methods on ToolContext, so callers can pass a context missing
openWorkspace or listOpenedWorkspaces; update assertToolContext to verify the
presence and function-ness of openWorkspace and listOpenedWorkspaces (alongside
the existing checks) and throw/assert if they are absent or not functions;
reference the ToolContext interface and ensure the guard checks the methods
named openWorkspace and listOpenedWorkspaces so partially-wired contexts fail
fast.

In `@src/mcp/workspace-router.ts`:
- Around line 742-762: The changed calculation in noteOpenedWorkspace is done
before normalizing source and ignores capabilityProfile, causing incorrect
diffs; update the logic in noteOpenedWorkspace (the changed variable
computation) to first determine the effectiveSource exactly as is later used
(i.e., treat current?.source === "startup" as persistent) and then compute
changed by comparing current?.repoId, current?.worktreeRoot,
current?.gitCommonDir, current?.source (or the effectiveSource) and
current?.capabilityProfile against resolved capabilityProfile so
capabilityProfile differences are detected; then proceed to set openedWorkspaces
using the same effectiveSource and capabilityProfile to keep detection and state
consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5d6be24b-f354-4746-9ba8-ebb5fde6fe6c

📥 Commits

Reviewing files that changed from the base of the PR and between 89a7641 and 0df8363.

⛔ Files ignored due to path filters (5)
  • docs/design/SURFACE_opened-workspace-paths.md is excluded by !**/*.md
  • docs/method/backlog/cool-ideas/SURFACE_opened-workspace-paths.md is excluded by !**/*.md
  • docs/method/backlog/dependency-dag.dot is excluded by !**/*.dot
  • docs/method/backlog/dependency-dag.svg is excluded by !**/*.svg
  • docs/three-surface-capability-matrix.md is excluded by !**/*.md
📒 Files selected for processing (19)
  • src/contracts/capabilities.ts
  • src/contracts/output-schema-fragments.ts
  • src/contracts/output-schema-mcp.ts
  • src/contracts/output-schemas.ts
  • src/mcp/burden.ts
  • src/mcp/context.ts
  • src/mcp/repo-tool-worker-context.ts
  • src/mcp/server-context.ts
  • src/mcp/server-tool-access.ts
  • src/mcp/tool-registry.ts
  • src/mcp/tools/workspace-list-opened.ts
  • src/mcp/tools/workspace-open.ts
  • src/mcp/workspace-router-model.ts
  • src/mcp/workspace-router.ts
  • test/unit/contracts/capabilities.test.ts
  • test/unit/contracts/output-schemas.test.ts
  • test/unit/mcp/opened-workspaces.test.ts
  • tests/playback/0078-three-surface-capability-baseline-and-parity-matrix.test.ts
  • tests/playback/SURFACE_capability-matrix-truth.test.ts
✅ Files skipped from review due to trivial changes (3)
  • src/mcp/tools/workspace-list-opened.ts
  • src/mcp/burden.ts
  • src/mcp/server-tool-access.ts

Comment thread src/mcp/context.ts
Comment thread src/mcp/workspace-router.ts
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/mcp/workspace-router.ts (1)

110-119: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Include runtimeLogs in capability-profile equality.

workspaceCapabilityProfilesEqual() still misses runtimeLogs, so a runtime-logs-only capability change can be treated as equal. That lets Line 324 skip the rebind path while noteOpenedWorkspace() updates the advertised profile, leaving currentBinding.capabilityProfile and the returned/opened view out of sync.

🔧 Minimal fix
 function workspaceCapabilityProfilesEqual(
   left: WorkspaceCapabilityProfile,
   right: WorkspaceCapabilityProfile,
 ): boolean {
   return left.boundedReads === right.boundedReads
     && left.structuralTools === right.structuralTools
     && left.precisionTools === right.precisionTools
     && left.stateBookmarks === right.stateBookmarks
+    && left.runtimeLogs === right.runtimeLogs
     && left.runCapture === right.runCapture;
 }

Also applies to: 324-327, 764-769

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/mcp/workspace-router.ts` around lines 110 - 119,
workspaceCapabilityProfilesEqual currently omits the runtimeLogs field so
capability changes that only toggle runtimeLogs are treated equal; update
workspaceCapabilityProfilesEqual to include left.runtimeLogs ===
right.runtimeLogs and then replace any ad-hoc comparisons (e.g., the spots that
decide whether to rebind in noteOpenedWorkspace and where
currentBinding.capabilityProfile is compared) to use this function so
runtimeLogs changes trigger the rebind/path update and keep
currentBinding.capabilityProfile and the returned/opened view in sync.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/playback/SURFACE_opened-workspace-paths.test.ts`:
- Around line 8-12: The afterEach cleanup loop currently stops if a cleanup
callback throws; update the afterEach block that iterates over the cleanups
array (the while loop using cleanups.pop()!()) so each callback is invoked
inside a try/catch (or similar per-callback error handling) to log or ignore the
individual error and continue running remaining cleanup functions; ensure the
loop still removes each callback from cleanups (so no duplicates remain) even
when a callback throws.

---

Duplicate comments:
In `@src/mcp/workspace-router.ts`:
- Around line 110-119: workspaceCapabilityProfilesEqual currently omits the
runtimeLogs field so capability changes that only toggle runtimeLogs are treated
equal; update workspaceCapabilityProfilesEqual to include left.runtimeLogs ===
right.runtimeLogs and then replace any ad-hoc comparisons (e.g., the spots that
decide whether to rebind in noteOpenedWorkspace and where
currentBinding.capabilityProfile is compared) to use this function so
runtimeLogs changes trigger the rebind/path update and keep
currentBinding.capabilityProfile and the returned/opened view in sync.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9897586a-727c-4fa6-a639-04855f41ea6d

📥 Commits

Reviewing files that changed from the base of the PR and between 0df8363 and 1a96483.

⛔ Files ignored due to path filters (3)
  • docs/design/SURFACE_opened-workspace-paths.md is excluded by !**/*.md
  • docs/method/retro/SURFACE_opened-workspace-paths/SURFACE_opened-workspace-paths.md is excluded by !**/*.md
  • docs/method/retro/SURFACE_opened-workspace-paths/witness/verification.md is excluded by !**/*.md
📒 Files selected for processing (4)
  • src/mcp/tool-registry.ts
  • src/mcp/tools/workspace-open.ts
  • src/mcp/workspace-router.ts
  • tests/playback/SURFACE_opened-workspace-paths.test.ts

Comment thread tests/playback/SURFACE_opened-workspace-paths.test.ts
Copy link
Copy Markdown
Owner Author

@codex Self-code-review pass against origin/main after a clean worktree check and git fetch origin. No P0/P1 blockers found. I do see several issues worth fixing before merge.

# Severity File / line Infraction Evidence Mitigation prompt
1 P2 Medium src/mcp/workspace-router.ts:110; src/mcp/workspace-router-model.ts:13 Capability-profile equality omits a declared field WorkspaceCapabilityProfile includes runtimeLogs (workspace-router-model.ts:18), but workspaceCapabilityProfilesEqual() compares every capability field except runtimeLogs (workspace-router.ts:114-118). That equality gates whether workspace_open skips rebind (workspace-router.ts:324-327) and whether opened records are considered changed. This overlaps an existing CodeRabbit finding and still appears valid locally. Verify the finding, add left.runtimeLogs === right.runtimeLogs to workspaceCapabilityProfilesEqual(), and add a focused regression or an explicit invariant test proving equality covers every WorkspaceCapabilityProfile key.
2 P2 Medium schemas/graft-structural-history.manifest.json:8; schemas/graft-structural-history.graphql:131; scripts/check-structural-history-schema-artifacts.ts:116 Missing contract coverage for a canonical generated type The schema defines canonical StructuralSourceSpan with @wes_registry(id: 515), and the generated artifact exports StructuralSourceSpan at src/generated/graft-structural-history.ts:97. The manifest requiredTypes list omits it, and the checker only validates the manifest-listed types. A future generated artifact could lose this type without the drift check noticing. Add StructuralSourceSpan to requiredTypes, refresh the manifest hashes, and add a test or script assertion that every non-exempt schema type with @wes_registry appears in the required-type coverage set.
3 P3 Low tests/playback/SURFACE_opened-workspace-paths.test.ts:8 Test cleanup can leave temp repos behind The afterEach loop calls cleanups.pop()!() directly. If one cleanup throws, later callbacks are never run. This overlaps an existing CodeRabbit finding and is still visible locally. Wrap each popped cleanup callback in per-callback error collection so all callbacks run, then throw an AggregateError after the loop if any cleanup failed.
4 P3 Low README.md:134; docs/MCP.md:54; GUIDE.md:21; docs/SETUP.md:119; docs/design/SURFACE_opened-workspace-paths.md:304 Public docs still teach the old daemon path The landed design says agents should normally use workspace_open and explicitly lists MCP/setup docs as an implementation step. Public docs still tell daemon users to call workspace_authorize then workspace_bind, and docs/MCP.md does not list workspace_open / workspace_list_opened in the tool groups. Update README, GUIDE, docs/MCP.md, and docs/SETUP.md so workspace_open is the normal agent-facing flow, workspace_list_opened is discoverable, and workspace_authorize / workspace_bind are positioned as lower-level daemon control-plane tools.
5 P3 Low docs/design/SURFACE_opened-workspace-paths.md:49; tests/playback/SURFACE_opened-workspace-paths.test.ts:141; docs/method/retro/SURFACE_opened-workspace-paths/witness/verification.md:351 Playback/witness overclaims verification The checked playback question claims reset coverage for cache, budget, saved state, metrics, and repo-state tracking. The test currently asserts saved state reset, lack of budget in a read receipt, and content from the new repo, but not cache, metrics, or repo-state tracking. The witness also says drift scanned 0 playback questions, so the checked design questions were not actually tied to the drift result. Either narrow the playback question to exactly what is asserted or add assertions for cache reset, metrics reset, and repo-state/causal slice reset; then regenerate the witness so drift scans the actual playback questions rather than reporting zero.
6 P3 Low CHANGELOG.md:10; src/contracts/capabilities.ts:25; package.json:113 Release notes omit shipped behavior The branch adds public MCP capabilities workspace_open and workspace_list_opened and patches audited transitive dependencies, but CHANGELOG.md only documents the structural-history schema authority in Unreleased. Add Unreleased entries for opened workspace paths and the dependency audit/security patch so the release notes match the branch behavior.
7 P4 Style docs/method/retro/SURFACE_opened-workspace-paths/witness/verification.md:335; :338 Markdown trailing whitespace git diff --check origin/main...HEAD reports trailing whitespace on both lines. Strip the trailing spaces and rerun git diff --check origin/main...HEAD.
8 P5 Nit docs/design/SURFACE_opened-workspace-paths.md:365 Completed decision still reads like an open question The Product Decisions section says “Should the list tool be named...” even though the decision is already made. Rewrite as a closed decision, e.g. List tool name: workspace_list_opened.

Suggested repair order: #1, #2, #3, then docs/witness cleanup (#4-#8).

@chatgpt-codex-connector
Copy link
Copy Markdown

To use Codex here, create an environment for this repo.

Copy link
Copy Markdown
Owner Author

@codex Follow-up self-review fixes pushed in 61747c5 (fix: resolve self-review findings).

Resolution summary:

Original finding Status
P2 runtimeLogs omitted from capability equality Fixed; equality now includes runtime-log posture, with a regression covering future runtime-log posture changes.
P2 StructuralSourceSpan missing from manifest drift coverage Fixed; manifest now requires StructuralSourceSpan, and the checker now verifies every @wes_registry schema type is listed in requiredTypes.
P3 playback cleanup stops on thrown cleanup Fixed; cleanup now collects per-callback errors and throws an AggregateError after all callbacks run.
P3 public docs still teach old daemon path Fixed; README, GUIDE, MCP docs, and SETUP now position workspace_open as the normal agent-facing path and keep authorize/bind as lower-level control-plane tools.
P3 playback/witness overclaims reset/drift coverage Fixed; playback now asserts cache, metrics, saved state, budget, and causal slice reset. Witness text now records the drift capture as incomplete instead of claiming coverage.
P3 changelog missing shipped behavior Fixed; changelog now includes opened workspace paths and dependency audit posture.
P4 trailing whitespace Fixed; git diff --check origin/main...HEAD passes.
P5 open-question wording Fixed; product decision now reads as a closed decision.

Validation run locally:

  • pnpm schema:structural-history:check
  • pnpm exec vitest run test/unit/contracts/graft-structural-history-schema.test.ts test/unit/mcp/workspace-binding.test.ts test/unit/mcp/opened-workspaces.test.ts tests/playback/SURFACE_opened-workspace-paths.test.ts
  • pnpm exec vitest run test/unit/mcp/workspace-binding.test.ts tests/playback/SURFACE_opened-workspace-paths.test.ts
  • pnpm lint
  • pnpm typecheck
  • git diff --check origin/main...HEAD
  • pnpm test -> 223 files / 1621 tests passed

@chatgpt-codex-connector
Copy link
Copy Markdown

To use Codex here, create an environment for this repo.

@flyingrobots
Copy link
Copy Markdown
Owner Author

@codex Self-discovered issue found during closure validation after resolving review threads.

# Severity File / line Infraction Evidence Mitigation prompt
1 P1 Merge-blocker tests/playback/CORE_v060-bad-code-burndown.test.ts:94 Full suite fixture is stale after tightening assertToolContext pnpm test now fails one test: Does assertToolContext validate the full context contract at construction time?. The test constructs validCtx without openWorkspace / listOpenedWorkspaces, but the production guard now correctly requires those methods. Update the playback fixture valid context to include openWorkspace and listOpenedWorkspaces, add or preserve assertions that missing required methods are rejected, then rerun the focused playback test and the full local gate.

@chatgpt-codex-connector
Copy link
Copy Markdown

To use Codex here, create an environment for this repo.

@flyingrobots
Copy link
Copy Markdown
Owner Author

@codex Activity Summary for Code Lawyer repair pass.

# Severity Source File Commit Outcome
1 P2 PR inline src/mcp/context.ts 8bd29c8 assertToolContext now validates openWorkspace and listOpenedWorkspaces; focused guard tests added.
2 P3 PR inline scripts/check-structural-history-schema-artifacts.ts 43b4884 Manifest required type names are escaped before RegExp construction; malformed manifest strings now report drift violations instead of throwing.
3 P3 PR inline scripts/check-structural-history-schema-artifacts.ts bfe8fa6 Wesley CLI version authority centralized in EXPECTED_WESLEY_CLI_VERSION and reused by tests.
4 P2 PR inline scripts/check-structural-history-schema-artifacts.ts 786e460 Wesley L1 registry hash now has a pinned constant and checker violation on drift.
5 P3 PR global schemas/graft-structural-history.graphql 68da5b4 Added source-span ordering invariants for offsets and present line ranges; manifest schema hash and changelog updated.
6 P5 PR global schemas/graft-structural-history.graphql 64fd77b Added rationale comment for the invariant holder _placeholder field; manifest schema hash updated.
7 P1 Self tests/playback/CORE_v060-bad-code-burndown.test.ts 8e32b04 Updated the playback fixture to match the expanded ToolContext contract and assert missing openWorkspace is rejected.

Validation:

Check Result
pnpm schema:structural-history:check Pass
pnpm lint Pass
pnpm typecheck Pass
git diff --check origin/main...HEAD Pass
pnpm test Pass: 223 files / 1627 tests
GitHub CI test (20) Pass
GitHub CI test (22) Pass
CodeRabbit status Pass: Review completed
Review threads All resolved by GraphQL check

Merge-gate note: checks are green and there are zero Changes Requested reviews, but the PR still has 0 approvals. The gate remains locked until the required 2 approvals arrive.

@chatgpt-codex-connector
Copy link
Copy Markdown

To use Codex here, create an environment for this repo.

@flyingrobots flyingrobots merged commit 6103810 into main May 27, 2026
3 checks passed
@flyingrobots flyingrobots deleted the cycle/CORE_structural-history-schema-authority branch May 27, 2026 01:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant